package humrum.weguide;

/*
 * Copyright (C) Weguide
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import greendroid.app.ActionBarActivity;
import humrum.weguide.views.ListSearch;
import humrum.weguide.views.Preferences;
import humrum.weguide.views.SearchPOI;

import java.util.List;
import java.util.Locale;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class WeGuide extends Activity implements OnClickListener,
		LocationListener {

	public static final String TAG = "WeGuide";

	private static final int GPS_ENABLED_RESULT = 1;

	/** Location fields */
	private LocationManager _locationManager;
	private Location _lastLocation;
	private Geocoder _geocoder;
	private List<Address> _listAddres;
	private GeocodeTask _geocodeTask;

	/** UI Components */
	private ImageButton nearPOI;
	private ImageButton searchPOI;
	private ImageButton favorites;
	private ImageButton config;
	private TextView textLocation;

	/** Preferences */
	@SuppressWarnings("unused")
	private SharedPreferences preferences;
	private SharedPreferences defaultPref;
	private int raio = 6;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// Fullscreen
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

		setContentView(R.layout.main);

		// views
		initViews();

		// location
		_locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		registerLocationListener();
		if (!_locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
			alertNoGPSEnabled();
		} else {
			useLastKnownLocation();
		}
		// preferences
		loadPreferences();
	}

	private void initViews() {
		nearPOI = (ImageButton) findViewById(R.id.bt_near_poi);
		nearPOI.setOnClickListener(this);

		searchPOI = (ImageButton) findViewById(R.id.bt_search_poi);
		searchPOI.setOnClickListener(this);

		favorites = (ImageButton) findViewById(R.id.bt_favorites);
		favorites.setOnClickListener(this);

		config = (ImageButton) findViewById(R.id.bt_config);
		config.setOnClickListener(this);

		textLocation = (TextView) findViewById(R.id.textLocation);
	}

	/**
	 * Gets user preferences
	 */
	private void loadPreferences() {
		// user
		preferences = this.getSharedPreferences(Preferences.SHARED_PREF_NAME,
				Activity.MODE_PRIVATE);
		// default
		defaultPref = PreferenceManager
				.getDefaultSharedPreferences(getApplicationContext());
		// raio da busca
		raio = defaultPref.getInt("custumRaio", 6);
	}

	@Override
	protected void onPause() {
		super.onPause();
		unregisterListener();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		unregisterListener();
		finish();
	}

	@Override
	protected void onResume() {
		super.onResume();
		registerLocationListener();
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			this.onDestroy();
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		final MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.main_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.mlogin:
			// login
			return true;
		case R.id.mpref:
			// pref
			openPreferences();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	/**
	 * Init views
	 */
	public void onClick(View v) {
		Intent intent;
		if (v == nearPOI) {
			openNearPoiActivity();
		} else if (v == searchPOI) {
			intent = new Intent(this, SearchPOI.class);
			startActivity(intent);
		} else if (v == favorites) {
			// favorites
		} else if (v == config) {
			openPreferences();
		}
	}

	private void openPreferences() {
		startActivity(new Intent(this, Preferences.class));
	}

	private void openNearPoiActivity() {
		if (_lastLocation != null) {
			Intent intent;
			// raio da busca
			raio = defaultPref.getInt("custumRaio", 6);
			// prepare params
			intent = new Intent(this, ListSearch.class);
			intent.putExtra("LAT", String.valueOf(_lastLocation.getLatitude()));
			intent.putExtra("LNG", String.valueOf(_lastLocation.getLongitude()));
			intent.putExtra("RAIO", String.valueOf(raio * 1000));
			intent.putExtra(ActionBarActivity.GD_ACTION_BAR_TITLE,
					"Buscar Pontos");
			startActivity(intent);
		} else {
			Toast.makeText(this, getString(R.string.waiting_for_location),
					Toast.LENGTH_SHORT).show();
		}
	}

	/** LOCATION METHODS */

	/**
	 * Remove listener
	 */
	private void unregisterListener() {
		_locationManager.removeUpdates(this);
	}

	/**
	 * Add listener
	 */
	private void registerLocationListener() {
		_locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				1000, 20, this);
	}

	/**
	 * Gets last position
	 */
	private void useLastKnownLocation() {
		_lastLocation = _locationManager
				.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		if (_lastLocation == null)
			_lastLocation = _locationManager
					.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

		if (_lastLocation != null) {
			// update location
			updateLocation(_lastLocation);
		}
	}

	/**
	 * Build alert no GPS enabled
	 */
	private void alertNoGPSEnabled() {
		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(R.string.gpsDisabled)
				.setCancelable(true)
				.setPositiveButton("Sim",
						new DialogInterface.OnClickListener() {

							public void onClick(DialogInterface dialog,
									final int which) {
								gpsSystemOptions();
							}
						})
				.setNegativeButton("Não",
						new DialogInterface.OnClickListener() {

							public void onClick(DialogInterface dialog,
									final int which) {
								Toast.makeText(getApplicationContext(),
										getString(R.string.msg_best_location),
										Toast.LENGTH_LONG).show();
								dialog.cancel();
							}
						});
		final AlertDialog alert = builder.create();
		alert.show();
	}

	/**
	 * Launch GPS Options
	 */
	private void gpsSystemOptions() {
		final ComponentName launch = new ComponentName("com.android.settings",
				"com.android.settings.SecuritySettings");
		final Intent intent = new Intent(Settings.ACTION_LOCALE_SETTINGS);
		intent.addCategory(Intent.CATEGORY_LAUNCHER);
		intent.setComponent(launch);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		startActivityForResult(intent, GPS_ENABLED_RESULT);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == GPS_ENABLED_RESULT) {
			if (resultCode == RESULT_OK) {
				// GPS Enabled use last location
				useLastKnownLocation();
			}
		}
	}

	/**
	 * Update user location
	 * 
	 * @param location
	 */
	private void updateLocation(Location location) {
		// Toast.makeText(this,
		// "Location: "+location.getLatitude()+" - "+location.getLongitude(),
		// Toast.LENGTH_LONG).show();
		_geocodeTask = new GeocodeTask(this);
		_geocodeTask.execute(location);
	}

	public void setGPSOnImage() {
		final ImageView gps_image = (ImageView) findViewById(R.id.gps_stats);
		gps_image.setImageResource(R.drawable.gps_view_on);
	}

	/** LOCATION LISTENER */
	public void onLocationChanged(Location location) {
		updateLocation(location);
	}

	public void onProviderDisabled(String provider) {
	}

	public void onProviderEnabled(String provider) {
	}

	public void onStatusChanged(String provider, int status, Bundle extra) {
	}

	/** ################################## */

	/**
	 * AsyncTask Geocoder
	 * 
	 * @author aderbal
	 * 
	 */
	private class GeocodeTask extends AsyncTask<Location, String, String> {

		private Context _context;

		public GeocodeTask(Context context) {
			_context = context;
		}

		@Override
		protected String doInBackground(Location... params) {
			_geocoder = new Geocoder(_context, Locale.getDefault());
			try {
				_listAddres = _geocoder.getFromLocation(
						params[0].getLatitude(), params[0].getLongitude(), 1);
				if (_listAddres.size() > 0) {
					return _listAddres.get(0).getAddressLine(0);
				}
			} catch (Exception e) {
				return "Não pode determinar";
			}
			return "Não pode determinar o endereço";
		}

		protected void onPostExecute(String result) {
			if (result != null)
				textLocation.setText(result);
			setGPSOnImage();
			try {
				this.finalize();
			} catch (Throwable e) {
			}
		}

	}
}